<?php

function unifiedpay_refund($refund_no, $order_id, $amount, $refund_desc){
	global $_G;
	$order = C::t('common_payment_order')->fetch($order_id);
	if(!$order || $order['status'] != 1) {
		return array('code' => 500, 'message' => lang('message', 'payment_order_no_exist'));
	}
	if($order['status'] == 3) {
		return array('code' => 500, 'message' => lang('plugin/unifiedpay', 'payment_already_refund'));
	}
	if($order['plugin']){
		$payment = unifiedpay_plugin_api($order['plugin'], false);
	}else{
		$payment = unifiedpay_plugin_init($order['channel']);
	}
	if(!$payment) {
		return array('code' => 500, 'message' => lang('message', 'payment_type_no_exist'));
	}
	if(!method_exists($payment, 'refund')){
		return array('code' => 500, 'message' => lang('plugin/unifiedpay', 'payment_channel_not_support'));
	}
	$result = $payment->refund($refund_no, $order['trade_no'], $order['amount'], $amount, $refund_desc);
	if($result['code'] == 200) {
		C::t('common_payment_order')->update($order_id, array('status' => 3));
		C::t('common_payment_refund')->insert(array(
			'order_id' => $order_id,
			'out_biz_no' => $refund_no,
			'amount' => $amount,
			'description' => $refund_desc,
			'status' => 2,
			'clientip' => $_G['clientip'],
			'remoteport' => $_G['remoteport'],
			'dateline' => time(),
			'refund_time' => $result['data']['refund_time']
		));
	}
	return $result;
}

function unifiedpay_query_order($order_id){
	$order = C::t('common_payment_order')->fetch($order_id);
	if(!$order) {
		return array('code' => 500, 'message' => lang('message', 'payment_order_no_exist'));
	}
	if($order['plugin']){
		$payment = unifiedpay_plugin_api($order['plugin'], false);
	}else{
		$payment = unifiedpay_plugin_init($order['channel']);
	}
	if(!$payment) {
		return array('code' => 500, 'message' => lang('message', 'payment_type_no_exist'));
	}
	$result = $payment->status($order['out_biz_no']);
	if($result['code'] == 200 && $order['status'] != 1 && $result['data']) {
		$payer = isset($result['data']['payer']) ? $result['data']['payer'] : null;
		unifiedpay_process_notify($order['out_biz_no'], $result['data']['trade_no'], $payer);
	}
	return $result;
}

function unifiedpay_transfer($channel, $transfer_no, $amount, $uid, $realname, $account, $title = '', $desc = '') {
	global $_G;
	$transfer_order = C::t('common_payment_transfer')->fetch_by_no($transfer_no);
	if($transfer_order) {
		if($transfer_order['status'] == 2) {
			return array('code' => 200, 'data' => array(
				'transfer_time' => $transfer_order['trade_time']
			));
		}
		elseif($transfer_order['status'] == 1) {
			return array('code' => 500, 'message' => lang('message', 'payment_transfer_exist'));
		}
		else{
			return array('code' => 500, 'message' => lang('message', 'payment_transfer_id_exist'));
		}
	}

	$payment = payment::get($channel);
	if(!$payment) {
		return array('code' => 500, 'message' => lang('message', 'payment_type_no_exist'));
	}
	if(!method_exists($payment, 'transfer')){
		return array('code' => 500, 'message' => lang('plugin/unifiedpay', 'payment_channel_not_support'));
	}
	$result = $payment->transfer($transfer_no, $amount, $realname, $account, $title, $desc);
	if($result['code'] == 200) {
		C::t('common_payment_transfer')->insert(array(
			'out_biz_no' => $transfer_no,
			'amount' => $amount,
			'subject' => $title,
			'description' => $desc,
			'realname' => $realname,
			'account' => $account,
			'channel' => $channel,
			'uid' => $uid,
			'status' => 2,
			'clientip' => $_G['clientip'],
			'remoteport' => $_G['remoteport'],
			'dateline' => time(),
			'trade_time' => $result['data']['transfer_time']
		));
	}
	return $result;
}

function unifiedpay_process_notify($out_biz_no, $trade_no, $payer = null){
	$order = C::t('common_payment_order')->fetch_by_biz_no($out_biz_no);
	if(!$order || $order['status']>0) {
		return $order;
	}
	$payment_time = time();

	$order['trade_no'] = $trade_no;
	$order['payment_time'] = $payment_time;
	$order['status'] = 1;
	if($payer) $order['payer'] = $payer;

	$status = C::t('common_payment_order')->update($order['id'], array('status' => 1));
	if($status) {
		$data['trade_no'] = $trade_no;
		$data['payment_time'] = $payment_time;
		if($payer) $data['payer'] = $payer;
		C::t('common_payment_order')->update($order['id'], $data);
		payment::retry_callback_order($order);
	}
	return $order;
}

function unifiedpay_process_return($out_biz_no, $trade_no, $payer = null){
	$order = unifiedpay_process_notify($out_biz_no, $trade_no, $payer);
	if(!$order) {
		showmessage('payment_order_no_exist', '', array(), array('showdialog' => true));
	}
	showmessage('payment_succeed', $order['return_url']);
}

function unifiedpay_plugin_init($channel){
	$config = C::t('common_setting')->fetch_setting('ec_'.$channel, true);
	if($config && $config['on'] == 1 && !empty($config['channel'])) {
		$plugin = $config['channel'];
		$classname = '\\unifiedpay\\plugins\\'.ucwords($plugin);
		$filename = DISCUZ_ROOT . 'source/plugin/unifiedpay/plugins/'.$plugin.'.php';
		if(file_exists($filename)){
			include $filename;
			if (class_exists($classname, false)){
				$object = new $classname();
				$object->channel = $channel;
				return $object;
			}
		}
	}
	return false;
}

function unifiedpay_plugin_call($object, $func, $args = []){
	if(!$object){
		return array('code' => 500, 'message' => lang('plugin/unifiedpay', 'payment_channel_not_on'));
	}
	if($func == 'wechat_authorize'){
		global $_G, $order;
		$pay_url = $_G['siteurl'] . 'plugin.php?id=unifiedpay:pagepay&out_biz_no='.$order['out_biz_no'].'&pay_channel=wechat&mode=1';
		return $pay_url;
	}
	if(!method_exists($object, $func)){
		return array('code' => 500, 'message' => lang('plugin/unifiedpay', 'payment_channel_not_support'));
	}
	return call_user_func_array([$object, $func], $args);
}

function unifiedpay_plugin_api($plugin, $func, $args = []){
	$classname = '\\unifiedpay\\plugins\\'.ucwords($plugin);
	$filename = DISCUZ_ROOT . 'source/plugin/unifiedpay/plugins/'.$plugin.'.php';
	if(file_exists($filename)){
		include $filename;
		if($func){
			if (class_exists($classname, false) && method_exists($classname, $func)){
				return call_user_func_array([new $classname(), $func], $args);
			}
		}else{
			if (class_exists($classname, false)){
				return new $classname();
			}
		}
	}
	return false;
}

function unifiedpay_plugin_getinfo($plugin){
	$classname = '\\unifiedpay\\plugins\\'.ucwords($plugin);
	$filename = DISCUZ_ROOT . 'source/plugin/unifiedpay/plugins/'.$plugin.'.php';
	if(file_exists($filename)){
		include $filename;
		if (class_exists($classname, false) && property_exists($classname, 'info')) {
			return $classname::$info;
		}
	}
	return false;
}

/**
 * 刷新支付插件列表
 * 扫描插件目录下的PHP文件，获取插件信息并更新到数据库
 * @return array 返回更新后的插件列表数组
 */
function unifiedpay_plugin_refresh(){
	$plugin_dir = DISCUZ_ROOT . 'source/plugin/unifiedpay/plugins/';// 定义插件目录路径
	$plugins = [];

	// 打开插件目录并遍历所有文件
	if (false != ($handle = opendir($plugin_dir))) {
		while (false !== ($file = readdir($handle))) {
			if (substr($file, -4) == '.php') {
				$plugin = substr($file, 0, -4);
				$info = unifiedpay_plugin_getinfo($plugin);
				if($info){
					unset($info['inputs']);
					$plugins[$plugin] = $info;
				}
			}
		}
		closedir($handle);
	}
	uasort($plugins, function($a, $b){
		if($a['sort'] > $b['sort']) return 1;
		elseif($a['sort'] < $b['sort']) return -1;
		else return 0;
	});

	 // 更新数据库中的插件列表
	C::t('common_setting')->update_setting('unifiedpay_plugins', $plugins);
	updatecache('setting');
	return $plugins;
}

if(!function_exists('is_https')){
	function is_https() {
		if(isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') {
			return true;
		}
		if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) == 'https') {
			return true;
		}
		if(isset($_SERVER['HTTP_X_CLIENT_SCHEME']) && strtolower($_SERVER['HTTP_X_CLIENT_SCHEME']) == 'https') {
			return true;
		}
		if(isset($_SERVER['HTTP_FROM_HTTPS']) && strtolower($_SERVER['HTTP_FROM_HTTPS']) != 'off') {
			return true;
		}
		if(isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) {
			return true;
		}
		return false;
	}
}
